/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package docview;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.TableColumnModelListener;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import javax.swing.DropMode;
import javax.swing.TransferHandler;
import tableprocessor.Table;


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Dema
 */

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceContext;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceListener;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JToolBar;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableColumnModel;
import tableprocessor.ColumnPare;
import javax.swing.KeyStroke;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.JButton;
import java.util.HashMap;
/**
 *
 * @author Dema
 */
class StringTransferable implements Transferable, ClipboardOwner {
  public static final DataFlavor plainTextFlavor = DataFlavor.plainTextFlavor;
  public static final DataFlavor localStringFlavor = DataFlavor.stringFlavor;
  private String string;
  public static final DataFlavor[] flavors = {
    StringTransferable.plainTextFlavor,
    StringTransferable.localStringFlavor
  };

  private static final List flavorList = Arrays.asList( flavors );

  public StringTransferable(String s)
  {
      string = s;
  }

  public synchronized DataFlavor[] getTransferDataFlavors() {
    return flavors;
  }
  public boolean isDataFlavorSupported( DataFlavor flavor ) {
    return (flavorList.contains(flavor));
  }

   public synchronized Object getTransferData(DataFlavor flavor)
    throws UnsupportedFlavorException, IOException {

    if (flavor.equals(StringTransferable.plainTextFlavor)) {
      String charset = flavor.getParameter("charset").trim();
      if(charset.equalsIgnoreCase("unicode")) {
    System.out.println("returning unicode charset");
    // uppercase U in Unicode here!
    return new ByteArrayInputStream(this.string.getBytes("Unicode"));
      } else {
    System.out.println("returning latin-1 charset");
    return new ByteArrayInputStream(this.string.getBytes("iso8859-1"));
      }
    } else if (StringTransferable.localStringFlavor.equals(flavor)) {
      return this.string;
    } else {
      throw new UnsupportedFlavorException (flavor);
    }
  }

    public void lostOwnership(Clipboard clpbrd, Transferable t) {

    }
}




public class ColorTable extends JTable //implements DropTargetListener,DragSourceListener, DragGestureListener
{


    private int mRow; // remember the row where the drag Started
    private int mColumn; // remember the Column where the drag Started
    private int[] mRows;
    private int[] mCols;
    private int rowLength;
    private int colLength;
    private Object mDataToSet;
    private DragSource source;
    private JPopupMenu menu;
    private Selection selection;
    private boolean merge;
    private int dragRow = -1;
    private int dragCol = -1;
    private int startDragRow = -1;
    private int startDragCol = -1;
    private int[] valueRow;
    private int valueCol = -1;
    private int[] rowSelection;
    private int colSelection = -1;
    private HashMap rowMap = new HashMap();

    private CopyAction copyAction = new CopyAction();
    private CutAction cutAction = new CutAction();
    private PasteAction pasteAction = new PasteAction();
    private PreviousAction prevAction = new PreviousAction();
    private NextAction nextAction = new NextAction();
    private List<Action> actions = new ArrayList<Action>();
    public List<DeleteActionListener> delListeners = new ArrayList<DeleteActionListener>();

    public void appendDeleteListener(DeleteActionListener listener)
    {
        delListeners.add(listener);
    }
    public void setSelectionData(Selection s)
    {
        selection = s;
    }

    public void setCurrentDragCell(int row, int col)
    {
        dragRow = row;
        dragCol = col;
    }

    public void highlightRow(int key,int rowNumber)
    {
        rowMap.put(key,rowNumber);
    }

    public void turnHighlightOff(int key)
    {
        rowMap.remove(key);
    }

    public void setStartDragCell(int row, int col)
    {
        startDragRow = row;
        startDragCol = col;
    }
    public void setPriceValue(int[] row, int col)
    {
        valueRow  = row;
        valueCol = col;
    }

    public void clearPriceValue()
    {
        valueCol = -1;
    }

    public int[] getPriceRows()
    {
        return valueRow;
    }

    public int getPriceCol()
    {
        return valueCol;
    }

    public void setRowSelection(int[] row, int col)
    {
        rowSelection = row;
        colSelection = col;
    }

    public void clearRowSelection()
    {
        
        colSelection = -1;
    }

    public ColorTable()
    {
        super();
        //source = new DragSource();
        //source.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this);
        //source.addDragSourceListener(this);
        menu = new JPopupMenu();
        Object pasteKey = "pasteKey";
        Object prevKey = "prevKey";
        Object cutKey = "cutKey";
        Object copyKey = "copyKey";
        Object nextKey = "nextKey";
        actions.add(copyAction);
        actions.add(cutAction);
        actions.add(pasteAction);
        actions.add(prevAction);
        actions.add(nextAction);
        for (int i = 0 ; i < actions.size(); i++)
        {
            actions.get(i).setTable(this);
        }
        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK),pasteKey);
        this.getActionMap().put(pasteKey, pasteAction);
        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_MASK),prevKey);
        this.getActionMap().put(prevKey, prevAction);
        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_MASK),cutKey);
        this.getActionMap().put(cutKey, cutAction);
        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK),copyKey);
        this.getActionMap().put(copyKey, copyAction);
        getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_Y, KeyEvent.CTRL_MASK),nextKey);
        this.getActionMap().put(nextKey, nextAction);

    }

    public void setTextToSubtable(int rowS,int colS, int rowE, int colE, String text )
    {
        if (    this.getColumnCount() > 0 &&
                this.getColumnCount() >= colE &&
                this.getRowCount() > 0 &&
                this.getRowCount() >= rowE && rowS >= 0 && colS >= 0 && rowE >= 0 && colE >= 0)
        {
                for (int i = rowS; i <= rowE; i++)
                {
                    for (int j = colS; j <= colE; j++)
                    {
                        this.setValueAt(text, i, j);
                    }
                }
        }
    }

    public boolean isInTable(int x, int y)
    {
        return (x>=0 && y>=0 && x<this.getColumnCount() && y< this.getRowCount());
    }

    public JPopupMenu getPopupMenu()
    {
        return menu;
    }
    public void setMergeEnabled(boolean state)
    {
        merge = state;
    }

    private class PopupTriggerListener extends MouseAdapter {
      public void mousePressed(MouseEvent ev) {
        if (ev.isPopupTrigger()) {
          //menu.show(ev.getComponent(), ev.getX(), ev.getY());
        }
      }

      public void mouseReleased(MouseEvent ev) {
        if (ev.isPopupTrigger()) {
         // menu.show(ev.getComponent(), ev.getX(), ev.getY());
        }
      }

      public void mouseClicked(MouseEvent ev) {
      }
    }
    public void fillPopupMenu(Iterator<ColumnPare> iter)
    {
        //menu = new JPopupMenu();
        //while(iter.hasNext())
        //{
          //  menu.add(new  JCheckBoxMenuItem(iter.next().getDbcol().getName()));
        //}
    }

    /*
    public void dragDropEnd(DragSourceDropEvent dsde) {
// TODO Auto-generated method stub
    }

    public void dragGestureRecognized(DragGestureEvent dge) {
        // TODO Auto-generated method stub
        try{
            StringTransferable transferData;
            mRows = getSelectedRows();
            mCols = getSelectedColumns();
            rowLength = mRows.length;
            colLength = mCols.length;
           // Point pt = dge.getDragOrigin();
           // mRow = rowAtPoint(pt);
           // mColumn = columnAtPoint(pt);
            mRow = mRows[0];
            mColumn = mCols[0];
            setStartDragCell(mRow,mColumn);
            Object obj = getValueAt(mRow,mColumn);
            transferData = new StringTransferable(obj.toString());



        System.out.println("drag gesture recognized");
        source.startDrag(dge,DragSource.DefaultMoveDrop,transferData, this);
        }
        catch (Exception e)
        {
               System.out.println("Gesture exception");
        }
    }

    public void drop(DropTargetDropEvent dtde) {
        // TODO Auto-generated method stub
        System.out.println("drop methUnsupported type od start");
        try {
        dtde.acceptDrop(DnDConstants.ACTION_MOVE);
        System.out.println("drop accept");
        Point p = dtde.getLocation();
        int row = rowAtPoint(p);
        int column = columnAtPoint(p);

        //mDataToSet = getValueAt(row,column);

        Transferable transferData = dtde.getTransferable();
        Object data = transferData.getTransferData(DataFlavor.stringFlavor);
        String s = new String();
        try
        {
            for(int i = 0,r = row; i< mRows.length; i++,r++)
            {
                for(int j = 0,col = column; j<mCols.length; j++,col++)
                {
                    if(!merge)
                    {
                        Object objOld = ((DocTableModel)getModel()).getValueAt(r, col);
                        Object objNew = ((DocTableModel)getModel()).getValueAt(mRows[i], mCols[j]);
                        ((DocTableModel)getModel()).setValueAt(objNew,r,col);
                        ((DocTableModel)getModel()).setValueAt(objOld,mRows[i],mCols[j]);
                    }
                    else
                    {
                        Object objNew = ((DocTableModel)getModel()).getValueAt(mRows[i], mCols[j]);
                        s+=objNew.toString()+" ";
                    }

                }

            }
            if (merge)
                ((DocTableModel)getModel()).setValueAt(s,row,column);
           }
           catch( Exception e)
           {

           }
//        if(!merge)
//        {
//            ((DocTableModel)getModel()).setValueAt(data,row, column);
//            ((DocTableModel)getModel()).setValueAt(mDataToSet,mRow,mColumn);
//        }
//        else
//        {
//            Object obj = ((DocTableModel)getModel()).getValueAt(row, column);
//            String s = new String();
//            s = obj.toString() + data.toString();
//            ((DocTableModel)getModel()).setValueAt(s,row, column);
//        }

        dtde.dropComplete(true);
        setStartDragCell(-1,-1);
        setCurrentDragCell(-1,-1);
        repaint();
        System.out.println("drop end");
        } catch (Exception e) {
        }
    }

    public void dragEnter(DropTargetDragEvent dtde) {


        dtde.acceptDrag(DnDConstants.ACTION_MOVE);

    }

    public void dragOver(DropTargetDragEvent dtde) {
        Point p = dtde.getLocation();
        int row = rowAtPoint(p);
        int column = columnAtPoint(p);
        setCurrentDragCell(row,column);
        repaint();
        dtde.acceptDrag(DnDConstants.ACTION_MOVE);
    }

    public void dropActionChanged(DropTargetDragEvent dtde) {
        dtde.acceptDrag(DnDConstants.ACTION_MOVE);
    }

    public void dragExit(DropTargetEvent dte) {

    }

    public void dragEnter(DragSourceDragEvent dsde) {
        DragSourceContext context = dsde.getDragSourceContext();

      int myaction = dsde.getDropAction();
      if( (myaction & DnDConstants.ACTION_MOVE) != 0) {
    context.setCursor(DragSource.DefaultMoveDrop);

      } else {
    context.setCursor(DragSource.DefaultMoveNoDrop);
      }

    }

    public void dragOver(DragSourceDragEvent dsde) {

    }

    public void dropActionChanged(DragSourceDragEvent dsde) {

    }

    public void dragExit(DragSourceEvent dse) {

    }*/

            @Override
            public void tableChanged(TableModelEvent e) {
                super.tableChanged(e);

                repaint();
            }

            @Override
            public Component prepareRenderer(TableCellRenderer renderer,
                    int row, int col) {
                Component c = super.prepareRenderer(renderer, row,    col);
                if ((row == startDragRow) && (col == startDragCol))
                {
                    c.setBackground(Color.gray);
                }
                else
                    c.setBackground(Color.white);
                if (isCellSelected(row,col))
                    c.setBackground(Color.blue);
                if ((row == dragRow)&&(col == dragCol))
                {
                    c.setBackground(Color.gray);
                }
                if (col == valueCol)
                {
                   for (int i = 0; i <valueRow.length; i++)
                       if (row == valueRow[i])
                            c.setBackground(Color.red);
                }
                if (colSelection != -1)
                {
                    for (int i = 0; i<rowSelection.length; i++)
                        if (row == rowSelection[i])
                            if (col == colSelection)
                                c.setBackground(Color.red);
                            else
                                c.setBackground(Color.gray);
                }
                Collection collection = rowMap.values();
                Iterator it = collection.iterator();
                while(it.hasNext())
                    if(row == it.next())
                        c.setBackground(Color.yellow);
                 /*
                else
                {
                    if (selection != null)
                    {
                        if ((row>=selection.getY()) && (row<= (selection.getY() + selection.getHight() ))
                            && (col>=selection.getX()) && (col<= (selection.getX()+selection.getWidth())))
                                c.setBackground(Color.green);
                        else
                            c.setBackground(getBackground());
                    }
                    else {
                        c.setBackground(Color.white);
                    }
                }*/
                return c;
            }
//            @Override
//            public void changeSelection(int rowIndex, int columnIndex,
//                    boolean toggle, boolean extend) {
//                    super.changeSelection(rowIndex, columnIndex, true, false);
//            }
}
